package nju.software.tagmanager.service.impl;

import com.aspose.pdf.operators.EX;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import nju.software.tagmanager.common.context.BaseContext;
import nju.software.tagmanager.common.exception.*;
import nju.software.tagmanager.mapper.*;
import nju.software.tagmanager.pojo.dto.ServiceQueryDTO;
import nju.software.tagmanager.pojo.dto.TagPageQueryDTO;
import nju.software.tagmanager.pojo.entity.RelCategoryTag;
import nju.software.tagmanager.pojo.entity.RelTagItem;
import nju.software.tagmanager.pojo.entity.Tag;
import nju.software.tagmanager.pojo.vo.ItemVO;
import nju.software.tagmanager.pojo.vo.TagVO;
import nju.software.tagmanager.service.TagService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 97942
 * @description 针对表【tag(标签表)】的数据库操作Service实现
 * @createDate 2024-01-12 16:03:24
 */
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag>
        implements TagService {

    @Resource
    private TagMapper tagMapper;

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private ItemMapper itemMapper;

    @Resource
    private RelCategoryTagMapper relCategoryTagMapper;

    @Resource
    private RelTagItemMapper relTagItemMapper;

    @Override
    public List<Tag> find(ServiceQueryDTO query) {
        return tagMapper.find(query);
    }

    @Override
    public IPage<TagVO> search(TagPageQueryDTO query) {
        try {
            Page<TagVO> tagVOPage = new Page<>(query.getPage(), query.getLimit());
            IPage<TagVO> result = tagMapper.search(query, tagVOPage);
            result.getRecords().forEach(tag -> {
                tag.setCategories(categoryMapper.findByTagId(tag.getId()));
                tag.setItems(itemMapper.findByTagId(tag.getId()));
            });
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new SearchFailureException();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addTagByCategoryId(String tagName, Integer categoryId) {
        List<Tag> tags = tagMapper.selectList(new QueryWrapper<Tag>().eq("name", tagName));
        Tag tag = null;
        if (!tags.isEmpty()) {
            if (tags.size() > 1) {
                // never here cause tagName has a physical unique key,
                // here is just an example for you that reminds you to think twice each condition
                throw new DuplicateTagNameException();
            }
            tag = tags.get(0);
        }


        //如果是不分类添加标签，但已存在标签
        if (tag != null && categoryId == -1) {
            throw new TagAlreadyExistsException();
        }

        //如果查询的标签为空,无论是否分类,先新增标签
        if (tag == null) {
            tag = Tag.builder()
                    .name(tagName)
                    .createUserId(BaseContext.getCurrentUserId())
                    .build();
            tagMapper.insert(tag);
        }

        if (categoryId != -1) {
            List<RelCategoryTag> relCategoryTags = relCategoryTagMapper.selectList(new QueryWrapper<RelCategoryTag>()
                    .eq("category_id", categoryId)
                    .eq("tag_id", tag.getId()));
            if (!relCategoryTags.isEmpty()) {
                if (relCategoryTags.size() > 1) {
                    throw new DuplicateCategoryTagRelationException();
                }
                throw new CategoryTagRelationAlreadyExistsException();
            }
            RelCategoryTag rel = RelCategoryTag.builder()
                    .tagId(tag.getId())
                    .categoryId(categoryId)
                    .build();
            relCategoryTagMapper.insert(rel);

        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Integer id) {
        try {
            relCategoryTagMapper.delete(new QueryWrapper<RelCategoryTag>().eq("tag_id", id));
            relTagItemMapper.delete(new QueryWrapper<RelTagItem>().eq("tag_id", id));
        } catch (Exception e) {
            throw new TagDeletionException();
        }

    }

    @Override
    public void deleteCascadeById(Integer tagId) {
        List<Integer> itemIds = itemMapper.findOnlyFollowing(tagId).stream()
                .map(ItemVO::getId).collect(Collectors.toList());
        relTagItemMapper.delete(new QueryWrapper<RelTagItem>()
                .eq("tag_id", tagId));
        if (!itemIds.isEmpty()) {
            itemMapper.deleteBatchIds(itemIds);
        }
        tagMapper.deleteById(tagId);
    }

    @Override
    public List<TagVO> findOnlyFollowing(Integer categoryId) {
        return tagMapper.findOnlyFollowing(categoryId);
    }
}




